package bancosys.tec.utils.date;

import java.text.ParseException;
import java.text.SimpleDateFormat;

import org.joda.time.LocalDate;

/**
 * @created May 10, 2007
 * @author Gustavo Almeida
 */
public final class DateUtils {
    private static final String DATE_FORMAT = "dd/MM/yyyy";

    private static final String TIMESTAMP_FORMAT = "dd/MM/yyyy HH:mm:ss";

    /**
     * Construtor.
     */
    private DateUtils() {
        super();
    }

    /**
     * Converte a string de formato DD/MM/YYYY para um objeto calendar com os valores das horas, minutos, segundos e milisegundos zerados.
     * 
     * @param ddmmaaaa Data passado no formato das views JSP - DD/MM/AAAA
     * @return Retorna um objeto {@link Date}
     */
    public static Date getCalendarByViewDateDDMMYYYY(String ddmmaaaa) {
        if (ddmmaaaa == null) {
            return null;
        }

        int ano = Integer.parseInt(ddmmaaaa.substring(ddmmaaaa.lastIndexOf("/") + 1, ddmmaaaa.length()));
        int mes = Integer.parseInt(ddmmaaaa.substring(ddmmaaaa.indexOf("/") + 1, ddmmaaaa.lastIndexOf("/")));
        int dia = Integer.parseInt(ddmmaaaa.substring(0, ddmmaaaa.indexOf("/")));

        return new Date(ano, mes, dia);
    }

    /**
     * Converte a string de formato DD/MM/YYYY para um objeto calendar com os valores das horas, minutos, segundos e milisegundos zerados.
     * Caso seje passado uma data inexistente, irá soltar excecão.
     * 
     * @param ddmmaaaa Data passado no formato das views JSP - DD/MM/AAAA
     * @return Retorna um objeto {@link Date}
     */
    public static Date getNonLenientDateByViewDateDDMMYY(String ddmmaaaa) {
        if (ddmmaaaa == null) {
            return null;
        }

        int ano = Integer.parseInt(ddmmaaaa.substring(ddmmaaaa.lastIndexOf("/") + 1, ddmmaaaa.length()));
        int mes = Integer.parseInt(ddmmaaaa.substring(ddmmaaaa.indexOf("/") + 1, ddmmaaaa.lastIndexOf("/")));
        int dia = Integer.parseInt(ddmmaaaa.substring(0, ddmmaaaa.indexOf("/")));

        return new Date(ano, mes, dia, false);
    }

    /**
     * Converte um date para o string DD/MM/AAAA.
     * 
     * @param date data.
     * @return string DD/MM/AAAA.
     */
    public static String dateToStringDDMMYYYY(java.util.Date date) {
        if (date == null) {
            return null;
        }
        SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);
        return formatter.format(date);
    }

    /**
     * Obtém a string que representa o timestamp
     * 
     * @param timestamp timestamp
     * @return string
     */
    public static String timestampToString(Timestamp timestamp) {
        if (timestamp == null) {
            return null;
        }
        SimpleDateFormat format = new SimpleDateFormat(TIMESTAMP_FORMAT);
        return format.format(timestamp);
    }

    /**
     * Lê o timestamp contido no valor
     * 
     * @param value value
     * @return timestamp
     * @throws ParseException ParseException
     */
    public static Timestamp parseTimestamp(String value) throws ParseException {
        if (value == null) {
            return null;
        } else {
            SimpleDateFormat format = new SimpleDateFormat(TIMESTAMP_FORMAT);
            return new Timestamp(format.parse(value).getTime());
        }
    }

    /**
     * Retorna o dia 1 do ano da data passada.
     * 
     * @param date data.
     * @return data com o primeiro dia do ano.
     */
    public static Date getFirstDayOfYear(Date date) {
        return new Date(date.getYear(), 1, 1);
    }

    /**
     * Retorna o dia 1 do ano seguinte à data passada.
     * 
     * @param date data.
     * @return data com o primeiro dia do ano seguinte.
     */
    public static Date getFirstDayOfNextYear(Date date) {
        return new Date(date.getYear() + 1, 1, 1);
    }

    /**
     * Retorna o dia 1 do mesmo mês da data passada.
     * 
     * @param date data.
     * @return data com o primeiro dia do mesmo mês.
     */
    public static Date getFirstDayOfMonth(Date date) {
        return new Date(date.getYear(), date.getMonth(), 1);
    }

    /**
     * Retorna o dia 1 do mesmo mês seguinte à data passada.
     * 
     * @param date data.
     * @return data com o primeiro dia do próximo mês.
     */
    public static Date getFirstDayOfNextMonth(Date date) {
        LocalDate localDate = new LocalDate(date);
        localDate = localDate.plusMonths(1).withDayOfMonth(1);
        return new Date(localDate.getYear(), localDate.getMonthOfYear(), localDate.getDayOfMonth());
    }

    /**
     * @param dt data.
     * @return timestamp com o ultimo segundo do dia passado.
     */
    public static Timestamp createTimestampWithLastSecondOfTheDay(Date dt) {
        final int lastHour = 23;
        final int lastSecond = 59;
        final int lastMinute = 59;
        return new Timestamp(dt.getYear(), dt.getMonth(), dt.getDay(), lastHour, lastMinute, lastSecond, 0);
    }
}
